from google.appengine.ext import webapp
import wsgiref.handlers
import logging
import re

class WSGIApplication(object):
	def __init__(self, is_debug=False):
		self.__controller_path = "controllers"
		self.__controller_package = __import__(self.__controller_path)
		self.__controller_map = {}
		self.__template_path = "templates"
		self.__debug = is_debug
		self.current_request_args = ()

	def __call__(self, environ, start_response):
		request = webapp.Request(environ)
		response = webapp.Response()

		WSGIApplication.active_instance = self

		self.current_request_args = ()

		path = request.path[1:]
		path_parts = path.split("/", 1)
		controller_name = path_parts[0]
		if not controller_name:
			controller_name = "index"		

		controller = self._resolve_controller(controller_name)
		if controller:
			handler = controller()
			handler.initialize(request, response)
			try:
				method = environ['REQUEST_METHOD']
				if method == 'GET':
					handler.get()
				elif method == 'POST':
					handler.post()
				elif method == 'HEAD':
					handler.head()
				elif method == 'OPTIONS':
					handler.options()
				elif method == 'PUT':
					handler.put()
				elif method == 'DELETE':
					handler.delete()
				elif method == 'TRACE':
					handler.trace()
				else:
					handler.error(501)
			except Exception, e:
				handler.handle_exception(e, self.__debug)
		else:
			response.set_status(404)

		response.wsgi_write(start_response)
		return ['']


	def _resolve_controller(self, controller_name):
		controller = self.__controller_map.get(controller_name, None)
		if not controller:
			try:
				controller_module = getattr(self.__controller_package, controller_name)
				controller = getattr(controller_module, controller_name)
				self.__controller_map[controller_name] = controller
			except Exception:
				controller = None
				raise
		return controller


	def get_registered_handler_by_name(self, handler_name):
		return self.__controller_map.get(handler_name, None)


def startup(is_debug=False):
	wsgiref.handlers.CGIHandler().run(WSGIApplication(is_debug))	
